﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using EnvDTE;
using Microsoft.VisualStudio.CommandBars;
using stdole;

namespace LazyPlugins.DeclarativeAddinCreator.Helpers
{
    public class IconUtils
    {
        public static void AddCommandActionWithicon(CommandBar commandBar, string name, string buttonText, string buttonDescription, string iconFile, Type addinActionType, AddinCreatorContext context, int location, ButtonVisuals visuals)
        {
            object[] contextGuids = null;

            Command command;
            try
            {
                string fullName = String.Format("PabloPlugins.AttachToLazy.Connect.{0}", name);
                command = context.ApplicationObject.Commands.Item(fullName, 0);
                command.Delete();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
            command = context.Commands.AddNamedCommand2(context.AddInInstance,
                                                            name,
                                                            buttonText,
                                                            buttonDescription,
                                                            true, 59,
                                                            ref contextGuids);

           

            var control = (CommandBarButton)command.AddControl(commandBar, location);
            control.BeginGroup = (visuals == ButtonVisuals.StartsNewGroup);
            SetControlPicture(control, iconFile);
            AddinRegistry.SetRelatedAction(addinActionType, control, command, context.AddInInstance, context.ApplicationObject);

            try
            {
                //add a divider line between the last item with added and the item below it if possible
                commandBar.Controls[location + 1].BeginGroup = true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }

        private static Color GuessTransparentColor(Bitmap bitmap)
        {
            Color pixel = bitmap.GetPixel(0, 0);
            Color color2 = bitmap.GetPixel(bitmap.Width - 1, 0);
            Color color3 = bitmap.GetPixel(0, bitmap.Height - 1);
            Color color4 = bitmap.GetPixel(bitmap.Width - 1, bitmap.Height - 1);
            if (pixel == color2)
            {
                return pixel;
            }
            if (color2 == color3)
            {
                return color2;
            }
            if (color3 == color4)
            {
                return color3;
            }
            return color4;
        }


        protected static Bitmap PrepareImage(Image image, Color transparentColor)
        {
            var bitmap = new Bitmap(image);
            var bitmap2 = new Bitmap(0x10, 0x10, PixelFormat.Format24bppRgb);
            Color color = GuessTransparentColor(bitmap);
            for (int i = 0; i < bitmap2.Width; i++)
            {
                for (int j = 0; j < bitmap2.Height; j++)
                {
                    Color baseColor = color;
                    if ((i < bitmap.Width) && (j < bitmap.Height))
                    {
                        baseColor = bitmap.GetPixel(i, j);
                    }
                    baseColor = Color.FromArgb(0xff, baseColor);
                    if (baseColor != color)
                    {
                        bitmap2.SetPixel(i, j, baseColor);
                    }
                    else if ((transparentColor != color) && (baseColor == transparentColor))
                    {
                        if (baseColor.R > 0)
                        {
                            bitmap2.SetPixel(i, j, Color.FromArgb(baseColor.R - 1, baseColor.G, baseColor.B));
                        }
                        else
                        {
                            bitmap2.SetPixel(i, j, Color.FromArgb(baseColor.R + 1, baseColor.G, baseColor.B));
                        }
                    }
                    else
                    {
                        bitmap2.SetPixel(i, j, transparentColor);
                    }
                }
            }
            return bitmap2;
        }

        protected static Bitmap PrepareMask(Image image)
        {
            var bitmap = new Bitmap(image);
            var bitmap2 = new Bitmap(0x10, 0x10, PixelFormat.Format24bppRgb);
            Color color = GuessTransparentColor(bitmap);
            for (int i = 0; i < image.Width; i++)
            {
                for (int j = 0; j < image.Height; j++)
                {
                    Color pixel = bitmap.GetPixel(i, j);
                    Color color3 = ((pixel == color) || (pixel.A < 0xff)) ? Color.White : Color.Black;
                    bitmap2.SetPixel(i, j, color3);
                }
            }
            return bitmap2;
        }

        protected static Icon GetIconFromFile(string path)
        {
            var psfi = new SHFILEINFO();
            SHGetFileInfo(path, 0x80, ref psfi, Marshal.SizeOf(psfi), 0x111);
            return Icon.FromHandle(psfi.hIcon);
        }

        static Color VS_MENUCOLOR = Color.FromArgb(0xec, 0xe9, 0xd8);

        public static void SetControlPicture(CommandBarButton button,string fileName)
        {
            if(!File.Exists(fileName))
            {
                return;
            }
            Image image1 = GetImageFromAnyFormat(fileName);
            Bitmap image2 = PrepareImage(image1, VS_MENUCOLOR);
            //Bitmap image3 = PrepareMask(image2);
            button.Picture = CreatePictureDisp(image2);
        }

        protected static Image GetImageFromAnyFormat(string path)
        {
            string str = path.ToLower();
            if (str.EndsWith(".exe") || str.EndsWith(".ico"))
            {
                return GetIconFromFile(path).ToBitmap();
            }
            return Image.FromFile(path, true);
        }


        protected static object OleLoadPictureFile(string fileName)
        {
            object iPictureDisp = null;
            OleLoadPictureFile(fileName, ref iPictureDisp);
            return iPictureDisp;
        }


        protected static StdPicture CreatePictureDisp(Image image)
        {
            return (StdPicture) ImageConverter.GetIPictureDispFromImage(image);
            //here is another approach:
//            string tempFileName = Path.GetTempFileName();
//            image.Save(tempFileName, ImageFormat.Bmp);
//            return (StdPicture) OleLoadPictureFile(tempFileName);
        }

        #region PInvoke declarations
        
        // ReSharper disable FieldCanBeMadeReadOnly.Local
        // ReSharper disable MemberCanBePrivate.Local   
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        private struct SHFILEINFO
        {
#pragma warning disable 649
            public IntPtr hIcon;
#pragma warning restore 649

#pragma warning disable 169
            public int iIcon;
#pragma warning restore 169
            public int dwAttributes;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
            public char[] szDisplayName;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
            public char[] szTypeName;
        }
        // ReSharper restore FieldCanBeMadeReadOnly.Local
        // ReSharper restore MemberCanBePrivate.Local

        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, int uFlags);

        [DllImport("oleaut32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern int OleLoadPictureFile(object fileName, [MarshalAs(UnmanagedType.IDispatch)] ref object iPictureDisp);

        #endregion
    }
}
